//	COPYRIGHT (C) 1981 BY BOARD OF TRUSTEES,
//	LELAND STANFORD JUNIOR UNIVERSITY

//APRIL 25, 1978
//BCPL-CONGEN, WRITTEN BY RAY CARHART.  THIS IS THE MAIN FILE FOR
//THE IMBED MODULE.  HERE USER I/O IS DONE, THE PROBLEM IS
//SET UP AND THE IMBEDDER IS CALLED.
GET "BCPLIB.GET"
GET "MYLIB.GET"
STATIC $( VECSPACE = VEC 5000; STACK = VEC 500; STACKPTR = 0 $);
LET DOSTUFF() BE
$( STATIC $( NTYPES=NIL; TYPENAME=NIL; TYPEVALENCE=NIL; ATTYPE=NIL;
             HMIN=NIL; NNODES=NIL; U=NIL; GSTART=1; GSTOP=NIL;
             SASTART=NIL; SASTOP=NIL; CTABLE=NIL;
             CTSTART=NIL; CTSTOP=NIL; NXBS=NIL; NSANODES=NIL;
             SATYPE = NIL; HMAX = NIL; XBSETS = NIL; XBSET = NIL;
             NUMISBS = NIL; SATYPES = NIL; SANNDS = NIL;
             MONOCOUNTS = NIL; NUMHS = NIL; ONBR = NIL; NDOT = NIL;
             DOTS = NIL; VMDEG = NIL; TYPEISBMIN = NIL; TYPEISBMAX = NIL;
             OKISBCOUNT = NIL $);
STATIC $( ARTYPE = NIL; ARPATRECS = NIL; NUMARPAT = NIL; ARPATNNDS = NIL $);
STATIC $( CTPTR = 1; NBR = NIL; IXBS = NIL $);
MANIFEST $( BLKSIZE = #200; SYMSIZE = 7; SYMSPERWD = 5; KEYROT = 7;
            ROWTERM = #177; ARSYM = #175; SSSIZE = 5000; RANIOCHAN = 6;
            P2WDSZ = 5; SYMMASK = #177; R2WDSZ = 32 $);
STATIC $( EBPTR = NIL; ENDBLOCK = VEC BLKSIZE-1; BLOCKCOUNT = NIL;
          STRUCSZ = NIL; NSTRUCS = NIL; FILIXLIST = VEC SSSIZE;
          KEYLIST = VEC SSSIZE; KFSTART = NIL; SAREC = NIL;
          INFILE = NIL; OUTFILE = NIL; MIDBLOCK = VEC BLKSIZE-1; INSOURCE = NIL;
          STRUCNUMBER = NIL; ISTRUC = NIL $);
STATIC $( SAIX = 0; NUMSA = NIL; SARECS = NIL $);
STATIC $( BPTR = NIL; PTRTOP = NIL; STRUCSZ0 = NIL; STRUCVEC = NIL;
          NNODESOUT = NIL; ITYPENAME = NIL $);
STATIC $( TYPENUM = NIL; PATSTART = NIL; PATSTOP = NIL; MAPPEDTO = NIL;
          NLNODES = NIL; LMINS = NIL; LMAXS = NIL; LNODE = NIL;
          NPATNODES = NIL; PATREC = NIL; NUMPAT = NIL; PATRECS = NIL;
          PATMINS = NIL; PATMAXS = NIL; PATNNDS = NIL; ATI = NIL;
          PTFLAG = NIL $);
STATIC $( NATH = NIL; ATHSTART = NIL; ATTYPEH = NIL $);
MANIFEST $( GSIZE0 = 1000 $);
STATIC $( GSCRATCH = VEC GSIZE0 $); //USED AS THE LAST ARG TO GROUPORCANON
STATIC $( STOPAFTER = NIL; STOPLAB = NIL $);

GET "SETFNS.BCL"
GET "MAKPAT.BCL"
GET "PATSIN.BCL"
GET "ARPSIN.BCL"
GET "GMATCH.BCL"
GET "ARPERC.BCL"
GET "GETISB.BCL"
GET "RDCYCC.BCL"
GET "CYCLES.BCL"
GET "ORANIO.BCL"
GET "GPRCAN.BCL"
GET "MAKESA.BCL"
GET "LABSA.BCL"
GET "EMBED.BCL"
GET "SEGFNS.BCL"

LET FETCHSTRUC() = VALOF
 $( STATIC $( CTPTR = NIL; NBR = NIL; NDIX = NIL; ONBR = NIL;
              NDOT = NIL; NISB = NIL; NH = NIL; SKIP = NIL $);
 STRUCNUMBER:=0;
 INPUT:=INFILE;
 NEXTSTRUC:
 SKIP:=FALSE;
 NBR:=[INCH()+80]REM 128;
 IF NBR=127 DO $( INPUT:=INSOURCE; RESULTIS FALSE $);
 IF NBR=126 DO $( STRUCNUMBER:=INNO(); INCH(); NBR:=[INCH()+80]REM 128 $);
 CTPTR:=1;
 NDIX:=0;
 WHILE NBR NE 127 DO
  $(
  NDIX+:=1;
  CTSTART!NDIX:=CTPTR;
  ARTYPE!NDIX:=1;
  ONBR:=0;
  NISB:=0;
  NDOT:=0;
  UNTIL NBR=0 DO
   $(
   TEST NBR=NDIX THEN NISB+:=1
   OR
    TEST NBR=125 THEN ARTYPE!NDIX:=2
    OR
     $(
     IF NBR=ONBR DO NDOT+:=1;
     ONBR:=NBR;
     CTABLE!CTPTR:=NBR;
     CTPTR+:=1
    $);
   NBR:=[INCH()+80]REM 128
   $);
  CTSTOP!NDIX:=CTPTR-1;
  NH:=TYPEVALENCE![ATTYPE!NDIX]-CTPTR+CTSTART!NDIX-NISB;
  IF NH<0 DO SKIP:=TRUE;
  NUMHS!NDIX:=NH;
  NUMISBS!NDIX:=NISB>>1;
  DOTS!NDIX:=NDOT;
  NBR:=[INCH()+80]REM 128
  $);
 IF SKIP DO $( OUTCHP('?'); GOTO NEXTSTRUC $);
 IF NUMSA>0 DO OUTCHP('#');
 INPUT:=INSOURCE;
 RESULTIS TRUE
 $);

LET PREIMLOOPTEST() = VALOF
 $( STATIC $( NT = NIL; I = NIL; ATI = NIL; NISBI = NIL $);
 NT:=0;
 WHILE NT<NTYPES DO $( NT:=NT+1; OKISBCOUNT!NT:=0 $);
 I:=GSTOP+1;
 WHILE I>1 DO
  $(
  I:=I-1;
  ATI:=ATTYPE!I;
  NISBI:=NUMISBS!I;
  TEST [TYPEISBMIN!ATI LE NISBI] BITAND [TYPEISBMAX!ATI GE NISBI] THEN
   OKISBCOUNT!ATI:=OKISBCOUNT!ATI+1
  OR IF OKISBCOUNT!ATI<TYPENUM!ATI DO RESULTIS FALSE
  $);
 RESULTIS TRUE
 $);

GSCRATCH!0:=GSIZE0;
INFILE:=FINDFILE("DSK",STRFILENAME(),CGEXT);
RETPART:=0

IF FILEEXISTS(SC1FILENAME(),CGEXT) DO
 $( INPUT:=FINDFILE("DSK",SC1FILENAME(),CGEXT);
    READRETURN()
 $)
INSOURCE:=INPUT;
OUTSIF("NUMBER OF ATOM TYPES:"); NTYPES:=INNO();
TYPENAME:=NEWVEC(NTYPES); TYPEVALENCE:=NEWVEC(NTYPES);
TYPEISBMIN:=NEWVEC(NTYPES); TYPEISBMAX:=NEWVEC(NTYPES);
OKISBCOUNT:=NEWVEC(NTYPES);
MONOCOUNTS:=NEWVEC(NTYPES);
TYPENAME!0:="**"; TYPENUM:=NEWVEC(NTYPES);
ATHSTART:=NEWVEC(NTYPES); NATH:=0;
OUTSIF("NAMES AND VALENCES:");
FOR I=1 TO NTYPES DO
 $(
 TYPENAME!I:=COPYS(INS());
 TYPEVALENCE!I:=INNO();
 TYPENUM!I:=0;
 MONOCOUNTS!I:=0;
 ATHSTART!I:=NATH;
 NATH+:=TYPEVALENCE!I+1
 $);
OUTSIF("NUMBER OF SUPERATOMS:");NUMSA:=INNO();
SATYPES:=NEWVEC(NUMSA); SANNDS:=NEWVEC(NUMSA);
OUTSIF("SA TYPES AND NNODES:"); NNODES:=0;
FOR I=1 TO NUMSA DO $( SATYPES!I:=FINDTYPE(INS()); SANNDS!I:=INNO();
 NNODES+:=SANNDS!I $);
SARECS:=NEWVEC(NUMSA);INPUT:=INFILE;
GSTOP:=INNO();
NNODES+:=GSTOP;
SASTOP:=NNODES;
NUMISBS:=NEWVEC(SASTOP);
INPUT:=INSOURCE;
OUTSIF("NUMBER OF PATTERNS:");NUMPAT:=INNO();
PATNNDS:=NEWVEC(NUMPAT);
IF NUMPAT>0 DO OUTSIF("NUMBER OF NODES FOR EACH PATTERN:");
FOR I=1 TO NUMPAT DO $( PATNNDS!I:=INNO(); NNODES+:=PATNNDS!I $);
PATRECS:=NEWVEC(NUMPAT);
PATMINS:=NEWVEC(NUMPAT); PATMAXS:=NEWVEC(NUMPAT);
ATTYPEH:=NEWVEC(NNODES);
HMIN:=NEWVEC(NNODES); NUMHS:=HMIN;
HMAX:=NEWVEC(NNODES-GSTOP)-GSTOP;
LMINS:=NEWVEC(NNODES-SASTOP)-SASTOP;
LMAXS:=NEWVEC(NNODES-SASTOP)-SASTOP;
FOR I=SASTOP+1 TO NNODES DO $( LMINS!I:=0; LMAXS!I:=0 $);
ARTYPE:=NEWVEC(NNODES); FOR I=1 TO NNODES DO ARTYPE!I:=1;

OUTSIF("NUMBER OF AROMATIC PATTERNS:"); NUMARPAT:=INNO();
ARPATNNDS:=NEWVEC(NUMARPAT);
IF NUMARPAT>0 DO OUTSIF("NUMBER OF NODES FOR EACH AROMATIC PATTERN:");
FOR I=1 TO NUMARPAT DO $( ARPATNNDS!I:=INNO(); NNODES+:=ARPATNNDS!I $);
ARPATRECS:=NEWVEC(NUMARPAT); ARPATRECS!0:=NUMARPAT;
ATTYPE:=NEWVEC(NNODES);
CTSTART:=NEWVEC(NNODES);
CTSTOP:=NEWVEC(NNODES);
DOTS:=NEWVEC(NNODES);
MAPPEDTO:=NEWVEC(NNODES); FOR I=1 TO NNODES DO MAPPEDTO!I:=0;
INPUT:=INFILE;
CTPTR:=1+2*[INNO()+GSTOP-1];
STRUCSZ0:=CTPTR+GSTOP-1;
FOR I=1 TO GSTOP DO
 $(
 ATI:=FINDTYPE(INS());
 ATTYPE!I:=ATI;
 ATTYPEH!I:=ATHSTART!ATI;
 TYPENUM!ATI+:=1
 $);
INPUT:=INSOURCE;
SASTOP:=GSTOP;
CTABLE:=STACK;
FOR SA=1 TO NUMSA DO
 $(
 OUTSIF("CTABLE FOR SUPERATOM "); OUTNOIF(SA); OUTSIF(" (TYPE ");
 OUTSIF(TYPENAME![SATYPES!SA]); OUTSIF("):*C*L"); SATYPE:=SATYPES!SA;
 TYPENUM!SATYPE-:=1;
 NSANODES:=SANNDS!SA;
 STRUCSZ0+:=NSANODES-1;
 FOR I=1 TO NSANODES DO
  $( LET NDIX = SASTOP+I;
  CTSTART!NDIX:=CTPTR;
  NUMISBS!NDIX:=0;
  OUTNOIF(I); OUTCHIF(':'); OUTCHIF(' ');
  ATI:=FINDTYPE(INS());
  ATTYPE!NDIX:=ATI;
  ATTYPEH!NDIX:=ATHSTART!ATI;
  TYPENUM!ATI+:=1;
  HMIN!NDIX:=INNO();
  HMAX!NDIX:=INNO();
  ARTYPE!NDIX:=INNO();
  NBR:=INNO();
  ONBR:=0;
  NDOT:=0;
  UNTIL NBR=0 DO
   $(
   IF NBR=ONBR DO NDOT+:=1;
   ONBR:=NBR;
   STACK!CTPTR:=(NBR>0 -> NBR+SASTOP,NBR-SASTOP);
   CTPTR+:=1;
   STRUCSZ0+:=1;
   NBR:=INNO()
   $);
  CTSTOP!NDIX:=CTPTR-1;
  DOTS!NDIX:=NDOT;
  VMDEG:=TYPEVALENCE!ATI-CTPTR+CTSTART!NDIX;
  CTPTR:=CTSTART!NDIX+TYPEVALENCE![ATTYPE!NDIX]-HMIN!NDIX;
  IF HMAX!NDIX>VMDEG DO HMAX!NDIX:=VMDEG
  $);
 OUTSIF("NUMBER OF XB SETS:"); NXBS:=INNO();
 XBSETS:=NEWVEC(NXBS);
 XBSETS!0:=NXBS;
 IF NXBS NE 0 DO OUTSIF("SIZE AND NODES FOR EACH XB SET;*C*L");
 FOR I=1 TO NXBS DO
  $(
  OUTSIF("SET "); OUTNOIF(I); OUTSIF(":");
  IXBS:=INNO();
  XBSET:=NEWVEC(IXBS);
  XBSET!0:=IXBS;
  FOR J=1 TO IXBS DO XBSET!J:=INNO()+SASTOP;
  XBSETS!I:=XBSET
  $);
 SASTART:=SASTOP+1;
 SASTOP+:=NSANODES;
 STACKPTR:=CTPTR;
 SARECS!SA:=MAKESAREC(SASTART,SASTOP,SATYPE,XBSETS);
 STACKPTR:=0;
 FOR I=NXBS TO 1 BY -1 DO FREEVEC(XBSETS!I);
 FREEVEC(XBSETS)
 $);

PATSTOP:=SASTOP;
READPATS();
READARPATS();
CTPTR-:=1;
GETISBRANGES("NUMBER OF ATOM TYPES FOR WHICH ISB RANGE IS TO BE TESTED:",
             0,100);
READCYCCONSTR();
OUTSIF("STOPAFTER (NON-POSITIVE ENTRY MEANS PRODUCE ALL STRUCTURES):");
STOPAFTER:=INNO();
UNLESS INPUT=TTY DO
 $(
 ENDREAD(INPUT);
 DELETEFILE(SC1FILENAME(),CGEXT);
 INPUT:=TTY
 $);

CTABLE:=NEWVEC(CTPTR);
WHILE CTPTR>0 DO $( CTABLE!CTPTR:=STACK!CTPTR; CTPTR-:=1 $);

STRUCSZ:=STRUCSZ0;
IF [STRUCSZ REM SYMSPERWD] NE 0 DO STRUCSZ+:=SYMSPERWD;
STRUCSZ:=STRUCSZ/SYMSPERWD;
EBPTR:=0;
KEYLIST!SSSIZE:=PLUSINF;
BLOCKCOUNT:=1;
NSTRUCS:=0;
KFSTART:=SSSIZE;
RANIOINIT(SC2FILENAME(),CGEXT);
ENDBLOCK!0:=0;
BLT(ENDBLOCK,ENDBLOCK+1,ENDBLOCK+BLKSIZE-1);

STRUCVEC:=NEWVEC(STRUCSZ0+SASTOP);
OUTFILE:=CREATEFILE("DSK",SC1FILENAME(),CGEXT);
OUTPUT:=OUTFILE;
NNODESOUT:=SASTOP-NUMSA;
OUTNO(NNODESOUT);
SPACES(1);
U:=1+[STRUCSZ0-3*NNODESOUT]/2;
OUTNOS(U);
FOR ITYPE=1 TO NTYPES DO
 $(
 ITYPENAME:=TYPENAME!ITYPE;
 FOR I=1 TO TYPENUM!ITYPE DO $( OUTS(ITYPENAME); SPACES(1) $);
 $);
ISTRUC:=0;
OUTPUT:=TTY;

STOPLAB:=LABEL(WRAPUP);
WHILE FETCHSTRUC() DO IF PREIMLOOPTEST() DO EMBED(GSTART,GSTOP);
WRAPUP:
OUTPUT:=OUTFILE;
OUTCH(47);
OUTPUT:=TTY;
ENDWRITE(OUTFILE);
RANIOTERMINATE(SC2FILENAME(),CGEXT);
DELETEFILE(SC2FILENAME(),CGEXT);
ENDREAD(INFILE);
IF NSTRUCS=0 DO
 $(
 DELETEFILE(SC1FILENAME(),CGEXT);
 OUTS("*C*LNO STRUCTURES WERE OBTAINED*C*L");
 OUTS("THE ORIGINAL LIST HAS BEEN RESTORED*C*L");
 TEST RETPART=0 THEN FINISH OR EXECUTERETURN()
 $);
OUTPUT:=CREATEFILE("DSK",SC2FILENAME(),CGEXT);
INPUT:=FINDFILE("DSK",TOPFILENAME(),CGEXT);
COPYSEGSTO(CHUNKSEP,SSHEADSTR,TRUE);
INNO(); IF INCH()=' ' DO STOPAFTER:=NSTRUCS;
TEST NSTRUCS=STOPAFTER THEN $( OUTNOS(NSTRUCS); OUTS("PARTIAL*C*L") $)
OR OUTNOL(NSTRUCS);
OUTNOS(1); OUTNOL(NSTRUCS); OUTNOS(U);
FOR I=1 TO NTYPES DO
 IF [TYPENUM!I]>0 DO $( OUTS(TYPENAME!I); SPACES(1); OUTNOS(TYPENUM!I) $);
NEWLINE(1);
SKIPSEG(CHUNKSEP);
OUTCH(CHUNKSEP);
COPYTOEND();
ENDREAD(INPUT);
INPUT:=TTY;
ENDWRITE(OUTPUT);
OUTPUT:=TTY;
NEWLINE(1);
INTERRUPTABLE(FALSE);
FILEREPLACE(STRFILENAME(),CGEXT,SC1FILENAME(),CGEXT);
FILEREPLACE(TOPFILENAME(),CGEXT,SC2FILENAME(),CGEXT);
OUTNO(NSTRUCS);
OUTS((NSTRUCS=1 -> " STRUCTURE WAS"," STRUCTURES WERE"));
OUTS(" OBTAINED*C*L");
IF NSTRUCS=STOPAFTER DO
 OUTS("!!!!! THIS IS ONLY A PARTIAL STRUCTURE LIST !!!!!*C*L");
INTERRUPTABLE(TRUE);
TEST RETPART=0 THEN FINISH OR EXECUTERETURN()
$);
LET START() BE
 $(
// ![#124]:=TOPORSTOP;
 INITIALISEIO(VECSPACE,5000);
 OUTPUT:=TTY;
 INPUT:=TTY;
 RECINIT();
 DOSTUFF()
 $)
